// Copyright (c) 2025 Huawei Technologies Co., Ltd.
// openUBMC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//         http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Description: 实现kvm客户端认证管理

#include <stdexcept>
#include "Utils.hpp"
#include "AuthenticationManager.hpp"

AuthenticationManager::AuthenticationManager(): authSessionCreator_(new ClientAuthentication())
    , sessionDeleter_(new DeleteSession()), host_(""), port_(""), userName_(""), passWord_(nullptr)
{
}

AuthenticationManager::~AuthenticationManager()
{
    delete sessionDeleter_;
    delete authSessionCreator_;
    DeleteCharArray(passWord_);
}

bool AuthenticationManager::HttpCreateSession(boost::string_view host, boost::string_view port,
    boost::string_view userName, const char* passWord, boost::string_view kvmMode)
{
    try {
        // 提供不带参数的HttpDeleteSession重载使用， 该重载会被异常处理时调用
        host_ = host.data();
        port_ = port.data();
        userName_ = userName.data();
        SafeStringUpdate(passWord_, passWord);

        authSessionCreator_->GetReqBody(userName, passWord, kvmMode);
        return authSessionCreator_->CreateSessionFromWeb(host, port, userName, passWord);
    } catch (...) {
        throw;
    }
}

bool AuthenticationManager::HttpDeleteSession(boost::string_view host, boost::string_view port,
    boost::string_view userName, const char* passWord)
{
    using status = boost::beast::http::status;
    try {
        auto res = authSessionCreator_->GetCallStatus();
        if (res == status::unknown) {
            boost::string_view errMsg = "Need to create a session first";
            throw std::logic_error(errMsg.data());
        }
        if (res != status::ok && res != status::created && res != status::accepted && res != status::bad_request) {
            boost::string_view errMsg = "No session can delete";
            throw std::logic_error(errMsg.data());
        }
        if (res == status::bad_request) {
            auto info = GetCreateSessionResultInfo();
            const HttpFailInfo* pFailType = boost::get<HttpFailInfo>(&info);
            if (pFailType->errorCode != "SessionModeIsExclusive") {
                throw std::logic_error(pFailType->errorCode.c_str());
            }
        }
        auto sessionId = authSessionCreator_->GetSessionId();
        // 别人创建的会话，自己取不到sessionId，是不能删除的
        if (sessionId == "") {
            boost::string_view errMsg = "The current session was not created by oneself";
            throw std::logic_error(errMsg.data());
        }
        const char* deleteUri = SafeStrCat("/redfish/v1/SessionService/Sessions/", sessionId.data());
        sessionDeleter_->SetUri(deleteUri);
        sessionDeleter_->GetReqBody(userName, passWord);
        auto result = sessionDeleter_->DeleteSessionFromWeb(host, port, userName, passWord);

        if (!result) {
            boost::string_view errMsg = "HTTP request returns failure without exception";
            throw std::logic_error(errMsg.data());
        }
        // 删除会话后，把原会话的信息重置
        authSessionCreator_->ResetHttpCall();
        return true;
    } catch (...) {
        throw;
    }
}

bool AuthenticationManager::HttpDeleteSession()
{
    if (host_ == "" || port_ == "" || userName_ == "" || passWord_ == nullptr) {
        return false;
    }
    return HttpDeleteSession(host_.c_str(), port_.c_str(), userName_.c_str(), passWord_);
}

HttpResInfo AuthenticationManager::GetCreateSessionResultInfo()
{
    using status = boost::beast::http::status;
    try {
        auto res = authSessionCreator_->GetCallStatus();
        if (res == status::unknown || (res != status::ok && res != status::created && res != status::accepted)) {
            return authSessionCreator_->GetFailInfo();
        }
        return authSessionCreator_->GetSuccInfo();
    } catch (...) {
        throw;
    }
}

boost::beast::http::status AuthenticationManager::GetCreateStatus()
{
    return authSessionCreator_->GetCallStatus();
}

boost::beast::http::status AuthenticationManager::GetDeleteStatus()
{
    return sessionDeleter_->GetCallStatus();
}

boost::string_view AuthenticationManager::GetSessionToken()
{
    using status = boost::beast::http::status;
    try {
        auto res = authSessionCreator_->GetCallStatus();
        if (res == status::unknown) {
            return "";
        }
        if (res != status::ok && res != status::created && res != status::accepted && res != status::bad_request) {
            return "";
        }
        if (res == status::bad_request) {
            auto info = GetCreateSessionResultInfo();
            const HttpFailInfo* pFailType = boost::get<HttpFailInfo>(&info);
            if (pFailType->errorCode != "SessionModeIsExclusive") {
                return "";
            }
        }
        return authSessionCreator_->GetToken();
    } catch (...) {
        throw;
    }
}